package com.example.springbootsqlite;

import com.example.springbootsqlite.entity.DocPo;
import org.assertj.core.util.Lists;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * @Description: TODO
 * @Author: llx
 * @Date: 2023.09.2717:58
 * @Copyright: Fujian Linewell Software Co., Ltd. All rights reserved.
 */
@Component
public class DataSourceUtil {
    public static Connection connection;
    public static Pattern p= Pattern.compile("[A-Z]");

    /**
     * DriverManager方式获取数据源
     * @param url jdbc:sqlite:static/temporary/jwuwb/
     * @param user ""
     * @param password ""
     */
    public static void getConnection(String url, String user,
                                     String password) {
        try {
            Class.forName("org.sqlite.JDBC");
            if(!url.startsWith("jdbc:sqlite:")){
                url = "jdbc:sqlite:" + url;
            }
            connection =  DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭数据源
     *
     * @throws SQLException
     */
    public static void closeConnection() throws SQLException {
        if (connection != null) {
            connection.close();
        }
    }

    public static <T> List<T> select(String sql, Class<T> t) throws Exception {
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> list = Lists.newArrayList();
        try {
            ps = connection.prepareStatement(sql);
            //返回一个结果集对象
            rs = ps.executeQuery();
            list = getList(rs, t);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (rs != null){
                rs.close();
            }
            if (ps != null){
                ps.close();
            }
            if (connection != null){
                connection.close();
            }
        }
        return list;
    }

    public static void main(String[] args) throws Exception {
        DataSourceUtil.getConnection("jdbc:sqlite:D:\\work\\workspace2\\springboot-sqlite_1\\sql\\slndata.db", "", "");
        List<DocPo> docList = DataSourceUtil.select("select * from doc", DocPo.class);
    }

    /**
     * 转换成数据库字段
     * @param param
     * @return
     */
    public static String camel4underline(String param){
        if(param==null ||param.equals("")){
            return "";
        }
        StringBuilder builder=new StringBuilder(param);
        Matcher mc=p.matcher(param);
        int i=0;
        while(mc.find()){
            builder.replace(mc.start()+i, mc.end()+i, "_"+mc.group().toLowerCase());
            i++;
        }

        if('_' == builder.charAt(0)){
            builder.deleteCharAt(0);
        }
        return builder.toString();
    }

    /**
     * 获取查询的列表
     * @param resultSet 结果集
     * @param o java 对象
     * @param <T> 泛型
     * @return
     * @throws SQLException
     */
    public static <T> List<T> getList(ResultSet resultSet , Class<T> o) throws Exception {
        List<T> list = Lists.newArrayList();
        if (resultSet != null){
            while (resultSet.next()){
                T et = o.newInstance();
                toObject(resultSet, et);
                list.add(et);
            }
        }
        return list;
    }


    /**
     * 结果集转换成对象
     * @param resultSet 查询结果集
     * @param object 实体对象
     */
    public static void toObject(ResultSet resultSet , Object object) throws SQLException {
        Class<?> c = object.getClass();
        Map<String, Object> map = new HashMap<>();
        //获取属性数组
        Field[] fields=c.getDeclaredFields();

        for (Field field : fields) {
            Class<?> type = field.getType();
            String simpleName = type.getSimpleName();
            String methodName = "get" + simpleName;
            //特殊类型对应转换
            if ("LocalDateTime".equals(simpleName)) {
                methodName = "getString";
            }
            if ("Integer".equals(simpleName) || "Boolean".equals(simpleName)) {
                methodName = "getInt";
            }
            String name = field.getName();
            if (!"serialVersionUID".equals(name)) {
                //反射处理获取类型转换
                String underline = camel4underline(name);
                Class<? extends ResultSet> aClass = resultSet.getClass();
                try {
                    Method method = aClass.getMethod(methodName, String.class);
                    Object invoke = method.invoke(resultSet, underline);
                    if ("Boolean".equals(simpleName)) {
                        int enable = (int) invoke;
                        invoke = enable == 1;
                    }
                    if ("LocalDateTime".equals(simpleName)) {
                        String time = (String) invoke;
                        String realTime = time.replaceAll("T", " ");
                        invoke = LocalDateTime.parse(realTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));;
                    }
                    map.put(name, invoke);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //获取对象方法
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            if (method.getName().startsWith("set")) {
                String name = method.getName();
                //获取属性名
                name = name.substring(3, 4).toLowerCase() + name.substring(4);
                if (map.containsKey(name)) {
                    Object o = null;
                    try {
                        o = map.get(name);
                        method.invoke(object, o);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}
